# evaluator/generate_report.py (最终完整版)

import json
from dataclasses import dataclass, asdict
from typing import List, Optional, Dict, Any
from openai import OpenAI
from config.API import api  # 在您的项目中，请使用此行


# ==============================================================================
# 1. 前端数据结构定义 (与您提供的代码一致)
# ==============================================================================

@dataclass
class CandidateSummary:
    candidate_name: str
    match_score: float
    core_skills_matched: List[str]
    soft_skills_detected: List[str]
    education_summary: str
    experience_summary: str
    resume_file_url: str
    interview_recommendation: str
    highlights: Optional[List[str]] = None

    def to_dict(self):
        data = asdict(self)
        data['highlights'] = data['highlights'] or []
        return data

@dataclass
class FeedbackItem:
    dimension: str
    score: float
    max_score: float
    comments: str

    def to_dict(self):
        return asdict(self)

@dataclass
class ScreeningResult:
    passed: bool
    final_score: float
    threshold_score: float
    feedback: List[FeedbackItem]
    suggestions: List[str]

    def to_dict(self):
        return {
            "passed": self.passed,
            "final_score": self.final_score,
            "threshold_score": self.threshold_score,
            "feedback": [item.to_dict() for item in self.feedback],
            "suggestions": self.suggestions
        }

# ==============================================================================
# 2. [新增] 调用AI生成洞察报告的函数
# ==============================================================================

def _call_ai_for_report_summary(
    unified_jd: Dict[str, Any],
    unified_resume: Dict[str, Any],
    matcher_result: Dict[str, Any]
) -> Dict[str, Any]:
    """
    当候选人通过筛选后，调用AI生成一份有洞察力的摘要报告。
    """
    client = OpenAI(api_key=api, base_url="https://dashscope.aliyuncs.com/compatible-mode/v1")
    
    # 步骤 1: 将Python字典转换为格式化的JSON字符串
    jd_str = json.dumps(unified_jd, ensure_ascii=False, indent=2)
    resume_str = json.dumps(unified_resume, ensure_ascii=False, indent=2)
    match_str = json.dumps({
        "total_score": f"{matcher_result.get('total_score', 0)*100:.1f}/100",
        "dimension_scores": {k: f"{v*100:.1f}/100" for k, v in matcher_result.get('details', {}).items()},
        "weights_used": matcher_result.get('weights_used', {})
    }, ensure_ascii=False, indent=2)

    # 步骤 2: 构建给AI的Prompt。
    # 我们使用Python的多行字符串（三引号）来清晰地组织结构。
    # f-string用于将我们准备好的JSON字符串嵌入到prompt中。
    prompt = f"""
    你是一位顶级的招聘总监，眼光毒辣，语言精练。现在，你需要根据以下三份信息，为一位通过初步筛选的候选人撰写一份简明扼要的筛选报告。

    ---
    ### 1. 职位要求 (JD)
    ```json
    {jd_str}
    Use code with caution.
    Python
    2. 候选人档案 (Resume)
    Generated json
    {resume_str}
    Use code with caution.
    Json
    3. 量化匹配分析结果
    Generated json
    {match_str}
    Use code with caution.
    Json
    请根据以上所有信息，严格按照以下JSON格式输出你的洞察报告。不要添加任何额外说明或Markdown标记。
    输出内容必须是且仅是一个合法的JSON对象。
    {{
    "candidate_name": "从候选人档案中提取的姓名，如果找不到则为'未知'",
    "education_summary": "一个简短的教育背景总结，格式如 '清华大学 - 计算机科学硕士'",
    "experience_summary": "一个简短的核心工作经验总结，格式如 '在阿里巴巴担任高级Java工程师5年'",
    "strengths": [
    "候选人的核心优势1 (必须具体，有数据或事实支撑)",
    "候选人的核心优势2 (例如：7年经验远超3年要求，完美匹配)",
    "候选人的核心优势3 (例如：具备JD中提到的稀有技能'高并发处理')"
    ],
    "potential_risks": [
    "需要关注的潜在风险或不足1 (例如：虽然经验丰富，但技术栈与JD要求的Go语言不符)",
    "潜在风险2 (如果找不到，可以是一个通用提醒，如'需在面试中考察项目细节')"
    ],
    "overall_assessment": "一段20-50字的综合评估和面试建议。语言风格要专业、果断。"
    }}
    """
    try:
        completion = client.chat.completions.create(
            model="qwen-plus",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.5,
        )
        response_content = completion.choices[0].message.content.strip()
        
        # 清理AI可能返回的Markdown代码块标记
        if response_content.startswith("```json"):
            response_content = response_content[7:].strip()
        if response_content.endswith("```"):
            response_content = response_content[:-3].strip()
            
        return json.loads(response_content)
    except Exception as e:
        print(f"❌ 调用AI生成洞察报告时失败: {e}")
        return {"error": str(e)}


def generate_report(
    matcher_result: Dict[str, Any],
    unified_resume: Dict[str, Any],
    unified_jd: Dict[str, Any], # [新增] 需要传入JD信息以供AI分析
    resume_url: str,
    threshold_score: float = 70.0
    ) -> dict:
    """
    根据匹配结果和简历信息，生成前端所需的最终报告。
    """
    raw_score = matcher_result.get("total_score", 0.0)
    final_score = raw_score * 100
    if not unified_resume:
        unified_resume = {}

    if final_score >= threshold_score:
        return _create_passed_report(final_score, threshold_score, matcher_result, unified_resume, unified_jd, resume_url)
    else:
        return _create_failed_report(final_score, threshold_score, matcher_result)

def _create_passed_report(
    final_score: float,
    threshold_score: float,
    matcher_result: Dict[str, Any],
    unified_resume: Dict[str, Any],
    unified_jd: Dict[str, Any],
    resume_url: str
    ) -> dict:
    """生成“通过”情况的报告，包含AI生成的洞察。"""
    print("INFO: 候选人通过筛选，正在生成洞察报告...")
    ai_summary = _call_ai_for_report_summary(unified_jd, unified_resume, matcher_result)

    # 如果AI总结失败，则回退到原来的模板化报告，保证程序不崩溃
    if "error" in ai_summary:
        print("WARN: AI洞察报告生成失败，将使用模板化报告作为后备。")
        # --- Fallback Logic (使用您原来的模板化逻辑) ---
        skills_obj = unified_resume.get("skills", {})
        soft_skills_detected = skills_obj.get("soft_skills", [])
        
        detail_scores = matcher_result.get("details", {})
        core_skills_matched = [dim for dim, score in detail_scores.items() if score > 0.7 and dim in ['skills', 'soft_skills']]
        
        recommendation = f"综合评分 {final_score:.1f}，高于阈值 {threshold_score}，建议进入下一轮面试。"
        highlights = [f"总匹配度高达 {final_score:.1f}%，与职位要求高度契合。"]
        if core_skills_matched:
            highlights.append(f"在 {' 和 '.join(core_skills_matched)} 等方面表现突出。")
        
        # 假设 basic_info 在初步解析时就已提取
        candidate_name = unified_resume.get("basic_info", {}).get("name", "姓名提取失败") 
        education_summary = "教育背景提取失败"
        experience_summary = "工作经验提取失败"
    else:
        # --- 使用AI生成的丰富内容 ---
        candidate_name = ai_summary.get("candidate_name", "姓名提取失败")
        education_summary = ai_summary.get("education_summary", "教育背景提取失败")
        experience_summary = ai_summary.get("experience_summary", "工作经验提取失败")
        highlights = ai_summary.get("strengths", [])
        highlights.extend([f"【注意】{risk}" for risk in ai_summary.get("potential_risks", [])])
        recommendation = ai_summary.get("overall_assessment", "建议面试。")
        soft_skills_detected = unified_resume.get('skills', {}).get('soft_skills', [])
        core_skills_matched = [dim for dim, score in matcher_result.get("details", {}).items() if score > 0.8]

    # 使用 CandidateSummary dataclass 组装最终报告
    summary = CandidateSummary(
        candidate_name=candidate_name,
        match_score=round(final_score, 2),
        core_skills_matched=core_skills_matched,
        soft_skills_detected=soft_skills_detected,
        education_summary=education_summary,
        experience_summary=experience_summary,
        resume_file_url=resume_url,
        interview_recommendation=recommendation,
        highlights=highlights
    )
    return summary.to_dict()

def _create_failed_report(
    final_score: float,
    threshold_score: float,
    matcher_result: Dict[str, Any]
    ) -> dict:
    """生成“不通过”情况的报告，此函数保持原样，无需调用昂贵的AI总结。"""
    feedback_items = []
    suggestions = []

    detail_scores = matcher_result.get("details", {})
    weights_used = matcher_result.get("weights_used", {})

    for dimension, score_raw in detail_scores.items():
        score_100 = score_raw * 100
        weight = weights_used.get(dimension, 0)
        
        comments = "表现良好"
        if score_100 < 50:
            comments = "与职位要求差距较大"
            if weight > 0.2: # 如果这是一个重要维度
                suggestions.append(f"请重点关注：候选人在核心维度“{dimension}”上存在明显短板。")
            else:
                suggestions.append(f"请注意候选人在“{dimension}”方面可能存在不足。")
        elif score_100 < threshold_score:
            comments = "基本满足要求，但非亮点"
        
        feedback_items.append(
            FeedbackItem(dimension=dimension, score=round(score_100, 2), max_score=100.0, comments=comments)
        )

    if not suggestions:
        suggestions.append("候选人综合素质较为均衡，但未达到优先推荐标准，建议放入人才库。")

    result = ScreeningResult(
        passed=False,
        final_score=round(final_score, 2),
        threshold_score=threshold_score,
        feedback=feedback_items,
        suggestions=suggestions
    )
    return result.to_dict()